// 模板带入
const template = `
<html xmlns:o="urn:schemas-microsoft-com:office:office"
  xmlns:x="urn:schemas-microsoft-com:office:excel"
  xmlns="http://www.w3.org/TR/REC-html40">
  <head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet>
    <x:Name>{fileName}</x:Name>
    <x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet>
    </x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]-->
    <style type="text/css">  
      tr { line-height: 40px; height: 40px; }
      th,td {
        text-align: center;
        mso-number-format:\@;
        vnd.ms-excel.numberformat:\@;
      }            
    </style>
  </head><body><table border="1" align="center" bordercolor="#000">{table}</table></body>
</html>`

function exportMethod(data, fileName, type = 'application/vnd.ms-excel') {
  const link = document.createElement('a')
  let blob = new Blob([data], { type })
  link.style.display = 'none'
  link.href = URL.createObjectURL(blob)
  link.download = fileName //下载的文件名
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
}

/************************************************************
 * @description		根据表头和数据导出带样式excel
 * @param {Array} head 表头
 * @param {Array} data 表格数据
 * @param {String} fileName 导出Excel文件名
 * @param {String} headBg 表头背景色
 * @param {String} title 表格title
 * @author			hauner
 * @date			2022-11-01
 ************************************************************/
export function exportExcelMethod(head, data, fileName, headBg = '#c0c0c0', title) {
  getMaxLevel(head) !== -1
    ? exportMoreHeadTable(head, data, fileName, headBg, title)
    : exportOnlyHeadTable(head, data, fileName, headBg, title)
}

function exportOnlyHeadTable(head, data, fileName, headBg, title) {
  // 表头逻辑
  let tableHead = '<tr>'
  head.forEach(col => (tableHead += `<th bgcolor="${headBg}" >&nbsp;${col.label}&nbsp;</th>`))
  tableHead += '</tr>'
  // title逻辑
  let t = title ? `<th  colspan="${head.length}" >${title}</th>` : ``
  let table = t ? `<tr>${t}</tr>` + tableHead : tableHead
  // 表体逻辑
  data.forEach(row => {
    let tableTr = ''
    head.forEach(col => (tableTr += `<td>&nbsp;${row[col.prop]}&nbsp;</td>`))
    table += `<tr>${tableTr}</tr>`
  })
  let file = template.replace('{fileName}', fileName).replace('{table}', table)
  exportMethod(file, fileName)
}

function exportMoreHeadTable(head, data, fileName, headBg, title) {
  let outMarge = {
    startCell: -1,
    basisRow: 0,
    basisCell: 0,
    maxRow: 0
  }
  let maxLevel = getMaxLevel(head)
  tagHeadIn(head)
  tagMaxLevel(head)
  let res = resetMergeHeaderInfo(head, maxLevel, outMarge, [])
  let lastChild = getLastChild(head)
  // 表头逻辑
  let tableHead = ''
  for (let i = maxLevel; i >= 0; i--) {
    tableHead += '<tr>'
    res.forEach(col => {
      let { e, s, item } = col
      if (item.maxLen != i) return
      let { c: ec, r: er } = e
      let { c: sc, r: sr } = s
      tableHead += `<th bgcolor="${headBg}" colspan=${ec - sc + 1} rowspan=${er - sr + 1} >&nbsp;${
        item.label
      }&nbsp;</th>`
    })
    tableHead += '</tr>'
  }

  // // title逻辑
  let t = title ? `<th  colspan="${lastChild.length}" >${title}</th>` : ``
  let table = t ? `<tr>${t}</tr>` + tableHead : tableHead
  // // 表体逻辑
  data.forEach(row => {
    let tableTr = ''
    lastChild.forEach(
      col =>
        (tableTr += `<td>&nbsp;${
          row[col.prop] === 0 ? row[col.prop] : row[col.prop] || '--'
        }&nbsp;</td>`)
    )
    table += `<tr>${tableTr}</tr>`
  })
  let file = template.replace('{fileName}', fileName).replace('{table}', table)
  exportMethod(file, fileName)
}

//  获取最大层级
//  只包含子级最大层级(不包含本级)
function getMaxLevel(arr) {
  console.log(arr)
  let max = -1
  function each(data, floor) {
    data.forEach(e => {
      max = Math.max(floor, max)
      e.child && each(e.child, floor + 1)
    })
  }
  each(arr, 0)
  return max
}

//  标记最大层级
function tagMaxLevel(tableHeader) {
  let maxLevel = getMaxLevel(tableHeader)
  tableHeader.forEach(el => {
    if (!el.child) {
      el.maxLen = maxLevel
    } else {
      tagMaxLevel(el.child)
      el.maxLen = maxLevel
    }
  })
}

function tagHeadIn(tableHeader) {
  tableHeader.forEach(el => (el.isOut = true))
}

//  获取当前下面所有子级
//  即：表头横向跨度单元格数量
function getLastChild(arr, result = []) {
  for (let i = 0, item; (item = arr[i++]); ) {
    !item.child ? result.push(item) : getLastChild(item.child, result)
  }
  return result
}

function resetMergeHeaderInfo(tableHeader, maxLevel, outMarge, result = []) {
  for (let i = 0; i < tableHeader.length; i++) {
    let item = tableHeader[i]
    //  纵向跨度
    const { maxLen } = item
    //  横向跨度
    let lastChild = getLastChild(item.child || [])
    //  s :  开始       e : 结束
    //  c : 列（横向）   r ： 行（纵向）
    let s = {}
    let e = {}
    if (!item.child) {
      if (item.isOut) {
        outMarge.startCell += 1
        outMarge.basisCell += 1
        s.r = 0
        e.r = maxLevel
        s.c = outMarge.startCell
        e.c = outMarge.startCell
        result.push({ s, e, item })
      } else {
        let r = maxLevel - (outMarge.basisRow + maxLen)
        r = Math.max(r, 0)
        s.c = outMarge.basisCell
        e.c = outMarge.basisCell
        s.r = outMarge.basisRow
        e.r = r + outMarge.basisRow + maxLen
        result.push({ s, e, item })
        outMarge.basisCell += 1
      }
    }
    if (item.child) {
      if (item.isOut) {
        s.r = 0
        e.r = 0
        outMarge.startCell += 1
        s.c = outMarge.startCell
        outMarge.startCell += lastChild.length - 1
        e.c = outMarge.startCell
        result.push({ s, e, item })
      } else {
        s.c = outMarge.basisCell
        e.c = outMarge.basisCell + lastChild.length - 1
        s.r = outMarge.basisRow
        e.r = outMarge.basisRow
        result.push({ s, e, item })
      }
      outMarge.basisRow += 1
      resetMergeHeaderInfo(item.child, maxLevel, outMarge, result)
    }
  }
  outMarge.basisRow -= 1
  return result
}


